perm filename TCPUSR.MAC[IP,SYS] blob sn#680232 filedate 1982-10-14 generic text, type T, neo UTF8
;CWL:<403-TCP>TCPUSR.MAC.40303  6-May-82 16:00:56, Edit by CLYNN
; Return IP/TCP options to user; Return error msg in TVTOPN failure
;<403-TCP>TCPUSR.MAC.40301 29-Jan-82 15:08:41, Edit by CLYNN
; Updated for TCP release 3
;[BBNF]<401-TCP>TCPUSR.MAC.78, 24-Jul-81 11:45:00, Ed: CLYNN
; Fix: Return error code even if abort in progress in USRBF*,
; No room return for USRINI
;SNARK:<401-TCP>TCPUSR.MAC.77 26-Mar-81 15:57:30, Edit by CLYNN
; USRBFE & USRBFF: Switch calls to BFRDUN and USTTUM so BFRDUN doesn't
;	DISMS while NOSKED
; USRABD: Don't let abort counter underflow
	SEARCH	INPAR,TCPPAR,PROLOG
	TTITLE	TCPUSR
	SUBTTL	TCP User Responses from TCP, William W. Plummer, 21MAR77
	SWAPCD

COMMENT	!

	Routines in this file are called from within the TCP to
	inform the user of various events that have occurred such as
	a connection opening or closing, or a buffer completion.

* USREVT ...  3 ...... User Event (Open/close)
* USRERR ...  7 ...... User Error condition (ReXmit timeout etc)
* USRURG ...  7 ...... Urgent data has arrived
* USRBFE ...  8 ...... User Buffer Empty
* USRBFF ...  9 ...... User Buffer Full
* USRABD ... 10 ...... User ABORT Done
  BFRDUN ... 10 ...... Handle completed buffer

* USRINI ... 11 ...... Initialize the user interface
	!
; USREVT(EVENT, TCB)		Connection open or close

;T1/	Event Code (Error Code) (377B35)
;TCB/	(Extended) Locked Connection block
;	CALL USREVT
;Ret+1:	Always

USREVT::LOCAL <CODE>
	MOVEM T1,CODE
	JN TSABT,(TCB),USREVX	; Ignore if ABORT in progress
	LOAD T1,TOPNF,(TCB)	; Index of open/close wait bit index
	LOAD T2,TSSYN,(TCB)	; Send state
	LOAD T3,TRSYN,(TCB)	; Recv state
	CAIN T2,NOTSYN		; Both NOT SYNCHRONIZED?
	 CAIE T3,NOTSYN
	  JRST USREV1

; State now NOT-NOT

	CALL CLRWTB		; Yes. Clear the wait bit (now CLOSED)
	JRST USREV2		; Cannot be SYN-SYN too

USREV1:
;	LOAD T2,TSSYN,(TCB)	; Get States again
;	LOAD T3,TRSYN,(TCB)
	CAIN T2,SYNCED		; Both fully synchronized?
	 CAIE T3,SYNCED
	  JRST USREV2		; No

; State now SYN-SYN

	JN TSOPN,(TCB),USREVX	; Jump if we have already said its open
	SETONE TSOPN,(TCB)	; Indicate that is now true
;	LOAD T1,TOPNF,(TCB)
	CALL SETWTB		; Set the wait bit.

REPEAT 0,<
	CALL GETRBS		; Get buffer size (e.g. packet size)
	SKIPG T1		; Present
> ; End of REPEAT 0
	  SETZ T1,		; Not present
	CALL TCPMXP		; Set buffer size (TSMXP)
USREV2:

; Any state

	JN TTVT,(TCB),USREV3	; Jump if a virtual terminal

; Here for non-TVT actions

	LOAD T1,TPICX,(TCB)	; Get Status-Change channel
	LOAD T2,TPIFX,(TCB)	; And FORKX to PSI
	CAIE T1,77		; No channel named
	 CAIN T2,-1		; or fork went away,
	  EXIT USREVX		; Means no PSI
	   CALL PSIRQ		; Set off the PSI
	JRST USREVX

; Here for TVT actions

USREV3:	CAIN CODE,OK		; What kind of event is this?
	  JRST USREV4		; Must be open

	MOVE T1,CODE		; Must be something to do with closing
	CALL TVTCLS		; Go close the Virtual terminal
	JRST USREVX

USREV4:	CALL TVTOPN		; Open a TCP Virtual Terminal
	JUMPE T1,USREVX		; Done if TVT assigned
	MOVEM T1,CODE		; Save error code (ELT+↑D4)

; Failed to assign a TVT to the connection.  The connection is now
; synchronized in both directions.  Try to send an error message to
; the other end before we abort the connection so the user has some
; idea of why the connection is being aborted.

	PUSH P,PKT		; Save these
	PUSH P,TPKT

	MOVX T1,4*<TVTFUE-TVTFUL> ; Message length, words
	SETZ T2,		; Have a TCB
	CALL TCPIPK		; Get empty packet
	  JRST USREV7		; Failed, just abort connection

	LOAD T1,PIPL,(PKT)	; Update packet byte length
	ADDI T1,4*<TVTFUE-TVTFUL>
	STOR T1,PIPL,(PKT)
	MOVX T1,<TVTFUE-TVTFUL>	; Move message into packet
	XMOVEI T2,TVTFUL
	LOAD T3,PTDO,(TPKT)
	ADD T3,TPKT
	CALL XBLTA

	SETONE <PEOL,PFIN>,(TPKT) ; This is the last data
	LOAD T1,TSSEQ,(TCB)	; Set the sequence #
	STOR T1,PSEQ,(TPKT)
	ADDI T1,4*<TVTFUE-TVTFUL>+1 ; End seq # is initial + data + FIN
	MODSEQ T1
	STOR T1,TSSEQ,(TCB)	; Advance Send sequence
	STOR T1,PESEQ,(PKT)	; Save recomputed end of packet

	SETZRO PPROG,(PKT)	; Don't bother with retransmissions
;	CALL SETRXP		; Setup packet rexmit parameters

	MOVE T1,TODCLK		; Current millisecond
	STOR T1,PTG,(PKT)	; Packet Time Generated
REPEAT 0,<
	SKIPN INTSCR		; In secure mode?
	  JRST 			; No.  Avoid the overhead.
	JE PPROG,(PKT),		; See if pkt will be ACK'd
	LOAD T2,TSLVN,(TCB)	; Guaranteed that KDC will here the word
	STOR T3,TSLVC,(TCB)	; So update the current level
: > ; End of REPEAT 0

	SETO T1,		; No TVT line block
	CALL EMTPKT		; Send the packet
	AOS FINSCT

; Now send a RESET to get connection closed

	SETZB T1,T2		; Have a TCB & no data
	CALL TCPIPK		; Get empty packet
	  JRST USREV7		; Give up if no space
	LOAD T1,TSSEQ,(TCB)	; Set the sequence #
	STOR T1,PSEQ,(TPKT)
	STOR T1,PESEQ,(PKT)	; Save recomputed end of packet
	SETONE <PRST>,(TPKT)	; Don't reply

	SETZRO PPROG,(PKT)	; Don't bother with retransmissions
;	CALL SETRXP		; Setup packet rexmit parameters

	MOVE T1,TODCLK		; Current millisecond
	STOR T1,PTG,(PKT)	; Packet Time Generated
REPEAT 0,<
	SKIPN INTSCR		; In secure mode?
	  JRST 			; No.  Avoid the overhead.
	JE PPROG,(PKT),		; See if pkt will be ACK'd
	LOAD T2,TSLVN,(TCB)	; Guaranteed that KDC will here the word
	STOR T3,TSLVC,(TCB)	; So update the current level
: > ; End of REPEAT 0

	SETO T1,		; No TVT line block
	CALL EMTPKT		; Send the packet
	AOS RSTSCT

; Following is done by TVTCLS
;	SETZRO TSUOP,(TCB)	; Fake a CLOSE
;	LOAD T1,TJCN,(TCB)	; Release the JCN
;	CALL RETJCN
USREV7:
	POP P,TPKT		; Restore registers
	POP P,PKT

	MOVE T1,CODE		; Error code
	CALL ABTCON		; Abort the connection (ABTCON/USREVT/TVTCLS)

USREVX:	RESTORE
	RET

TVTFUL:	BYTE (8)"4","2","1"," ","N","o"," ","f","r","e","e"," "
	BYTE (8)"t","e","r","m","i","n","a","l","s",15,12
TVTFUE:

; USRERR(Code)		Indicate TCP error condition to user
			; May be called for TVTs with either error

;T1/	TCP-style error code
;		EFP+↑D7  RST Received
;		ELP+↑D9  RX timeout
;TCB/	(Extended) Locked Connection block
;
;	CALL USRERR
;Ret+1:	Always

USRERR::NOSKED
	STOR T1,TERR,(TCB)	; Save the event code for user to see
	JN TSABT,(TCB),USRER1	; Forget PSI if ABORT in progress
	LOAD T1,TPICE,(TCB)	; Get the error channel
	LOAD T2,TPIFE,(TCB)	; Get the error FORKX
	CAIE T1,77		; No channel named
	 CAIN T2,-1		; or fork went away
	  CAIA			; Skip the PSI
	   CALL PSIRQ		; Poke that fork's channel
USRER1:
	LOAD T1,TERRF,(TCB)	; Index of the error flag
	CALL SETWTB		; Set it to wake up waiting process(es)
	OKSKED
	RET



; USRURG(TCB)		Alert user that Urgent data is to be read

;TCB/	(Extended) Locked Connection Block
;
;	CALL USRURG
;Ret+1:	Always.

USRURG::JN TSABT,(TCB),USRURX	; Forget if ABORT in progress
	LOAD T1,TPICU,(TCB)	; Get the URG channel
	LOAD T2,TPIFU,(TCB)	; and FORKX
	CAIE T1,77		; None named
	 CAIN T2,-1		; or fork went away
	  EXIT USRURX		; Skip the PSI
	   CALL PSIRQ		; Request the PSI in that fork
USRURX:	RET

; USRBFE(BFR)			User buffer empty condition (SEND, etc)
				; Never called for TVTs

;T1/	TCP-style event code and flags
;TCB/	(Extended) Locked Connection Block
;BFR/	(Extended) Buffer descriptor
;
;	CALL USRBFE
;Ret+1:	Always

USRBFE::PUSH P,T1		; Save the code for a second
	CALL SETTUM		; Make map user into our user space (NOSKED)
	POP P,T1		; Recover the code
	JE TSABT,(TCB),USRBE2	; Different error if ABORT in progress
	MOVX T1,<<ELP+↑D14>B7>	; Connection reset
USRBE2:
	LOAD T2,BHADR,(BFR)	; Origin of the Buffer Header
	LOAD T3,BCNT,(BFR)	; Get the count
	UMOVEM T3,BFRCNT(T2)	; Store into user space

	JUMPE T3,USRBE3		; Skip if whole buffer sent
	LOAD T4,TSBYT,(TCB)	; Reduce outstanding count
	SUB T4,T3		; by bytes not sent
	STOR T4,TSBYT,(TCB)
USRBE3:

	TXO T1,TCP%DN		; Buffer done bit
	MOVX T3,<-1B7+TCP%DN>	; Bits changed here
	AND T1,T3		; Flush stray bits
	XCTU [ANDCAM T3,BFRFLG(T2)] ; Clear in user space
	XCTU [IORM T1,BFRFLG(T2)] ; Set to tell the user it has finished
	CALL USTTUM		; Unmap the user space & OKSKED
	LOAD T1,TPICS,(TCB)	; Get the SEND done PSI Channel
	LOAD T2,TPIFS,(TCB)	; And forkx
	CALLRET BFRDUN		; Dispose of the buffer

; USRBFF(FLAGS,BFR)	User buffer filled (RECV)
			; Never called for TVTs

;T1/	TCP-style event code and flags (TCP%PU, TCP%UR, etc.)
;BFR/	(Extended) Buffer desciptor which is completing
;TCB/	(Extended) Locked Connection Block
;
;	CALL USRBFF
;Ret+1:	Always.

USRBFF::PUSH P,T1		; Save the code
	CALL SETTUM		; Map the user into our user space (NOSKED)
	POP P,T1		; Recover the code
	JE TRURG,(TCB),USRBFA	; Jump if not in receive urgent mode
	TXO T1,TCP%UR		; Give urgent flag in buffer
USRBFA:
	JE TSABT,(TCB),USRBF2	; Different error if ABORT in progress
	MOVX T1,<<ELP+↑D14>B7>	; Connection reset
USRBF2:
	LOAD T2,BHADR,(BFR)	; Get address of header in user space
	LOAD T3,BCNT,(BFR)	; Get count from monitor copy of header
	UMOVEM T3,BFRCNT(T2)	; Store into user copy
	LOAD T4,TRBS,(TCB)	; Amount of RECV buffer space
	SUB T4,T3		; The whole buffer is going back!
				; Shrinking the window is bad!!
	STOR T4,TRBS,(TCB)	; Leave what is left for window setting.
	TXO T1,TCP%DN		; Set the done bit
	MOVX T3,<-1B7+TCP%PU+TCP%UR+TCP%DN> ; Bit we change
	AND T1,T3		; Flush stray bits
	XCTU [ANDCAM T3,BFRFLG(T2)] ; Clear in user space
	XCTU [IORM T1,BFRFLG(T2)] ; Merge with user's header

	MOVX T1,<.RTJST(-1,PIDO)-<MINIHS+3>/4> ; Max IP option words
	XMOVEI T2,TCBIR(TCB)	; Received IP options
	HLRZ T3,BFROPT(BFR)	; Address for IP options
	SKIPE T3		; If none, don't return any
	  CALL BLTMU		; IP options to user

	MOVX T1,<.RTJST(-1,PTDO)-<MINTHS+3>/4> ; Max TCP option words
	XMOVEI T2,TCBTR(TCB)	; Received TCP options
	HRRZ T3,BFROPT(BFR)	; Address for TCP options
	SKIPE T3		; If none, don't return any
	  CALL BLTMU		; TCP options to user

USRBF9:	CALL USTTUM		; Unmap the user space & OKSKED
	LOAD T1,TPICR,(TCB)	; Get the RECV done PSI Channel
	LOAD T2,TPIFR,(TCB)	; And forkx
	CALLRET BFRDUN		; Dispose of the buffer

; USRABD(TCB)		User ABORT Done

;TCB/	(Extended) Locked Connection Block
;
;	CALL USRABD
;Ret+1:	Always

USRABD::NOSKED
	LOAD T1,TABTFX,(TCB)	; Get FORKX of ABORTer
IFKA <	CALL ABTPTR>		; Simulate the ADJBP ...
IFNKA <	ADJBP T1,FKABCP> 	; Get pointer to that fork's count
	LDB T2,T1
	SKIPE T2		; Don't let counter underflow
	  SUBI T2,1
	DPB T2,T1
	OKSKED
	RET


; BFRDUN(Channel, Forkx, Buffer, TCB)	Handle buffer done condition
					; Never called for TVTs
;T1/	PSI Channel
;T2/	FORKX to PSI
;BFR/	(Extended) Buffer
;TCB/	(Extended) Locked connection block
;
;	CALL BFRDUN
;Ret+1:	Always

BFRDUN:	NOSKED
	CAIE T1,77		; No channel named?
	 CAIN T2,-1		; Or fork went away?
	  CAIA			; Means no PSI
	   CALL PSIRQ		; Set off the PSI
	LOAD T1,BFRKX,(BFR)	; Fork wherein buffer lives
	HLRZ T1,FKPGS(T1)	; Get SPT index of UPT for that fork
	CALL DWNSHR		; Decrement share count
	JE BIDX,(BFR),BFRDU5	; Jump if no fork will be waiting
	MOVE T1,BFR		; The item to enqueue
	MOVE T2,TCPBDQ		; The buffer done queue
	CALL NQ			; Pick it up later
	LOAD T1,BIDX,(BFR)	; Get the wait bit index
	CALL SETWTB		; Make the user wake up now
	OKSKED
	EXIT BFRDUX

BFRDU5:	OKSKED
	MOVE T1,BFR		; What to release
	CALL RETBLK		; Return the free storage
BUFDUX:	RET

; USRINI			Initialize the user interface

USRINI::MOVEI T1,QSZ		; Size of a queue head
	CALL GETBLK		; Get space from INTSEC
	JUMPE T1,USRINX		; No room
	MOVEM T1,TCPBDQ		; Save for all to find
	CALL INITQ		; Initialize it
	SETO T1,		; All ok
USRINX:	RET

	T